﻿
namespace Gmantis.Imaging
{
    internal class Crc32
    {
        // Fields
        private long _crc;
        private static uint[] _crcTable;

        // Methods
        public static uint GetCrc(byte[] data)
        {
            Crc32 crc = new Crc32();
            crc.UpdateCrc(data);
            return crc.Value;
        }

        public void UpdateCrc(byte[] data)
        {
            this.UpdateCrc(data, 0, data.Length);
        }

        public void UpdateCrc(byte[] data, int offset, int count)
        {
            this._crc ^= (long)0xffffffffL;
            for (int i = offset; i < (offset + count); i++)
            {
                this._crc = CrcTable[(((int)this._crc) ^ data[i]) & 0xff] ^ (this._crc >> 8);
            }
            this._crc ^= (long)0xffffffffL;
        }

        // Properties
        private static uint[] CrcTable
        {
            get
            {
                if (_crcTable == null)
                {
                    _crcTable = new uint[0x100];
                    for (int i = 0; i < 0x100; i++)
                    {
                        uint num = (uint)i;
                        for (int j = 0; j < 8; j++)
                        {
                            num = ((num & 1) > 0) ? (0xedb88320 ^ (num >> 1)) : (num >> 1);
                        }
                        _crcTable[i] = num;
                    }
                }
                return _crcTable;
            }
        }

        public uint Value
        {
            get
            {
                return (uint)this._crc;
            }
        }
    }
}
